#include "mytcpsocket.h"
#include<QDir>
#include<QMessageBox>
#include<QFileInfo>
#include <QMutexLocker>
#include<QThread>
MyTcpSocket::MyTcpSocket(QObject *parent)
    : QTcpSocket{parent}
{
    connect(this,&MyTcpSocket::readyRead,this,&MyTcpSocket::recvMsg);

    connect(this,&MyTcpSocket::disconnected,this,[=](){
        //向主线程发送断开tcp信号，请求移除当前tcpsocket
        emit offline(this);
    });

    m_upLoad=false;
    m_timer=new QTimer(this);

    connect(m_timer,&QTimer::timeout,this,&MyTcpSocket::downLoadFileData);
}

MyTcpSocket::~MyTcpSocket()
{

}

void MyTcpSocket::copyDir(QString srcDir, QString destDir)
{
    QDir dir;
    dir.mkdir(destDir);
    dir.setPath(srcDir);
    QFileInfoList fileInfoList=dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
    QString srcTemp;
    QString destTemp;
    for(int i=0;i<fileInfoList.size();i++){
        // qDebug()<<"文件名/文件夹名："+fileInfoList.at(i).fileName();
        if(fileInfoList.at(i).isFile()){
            srcTemp=srcDir+"/"+fileInfoList.at(i).fileName();
            destTemp=destDir+"/"+fileInfoList.at(i).fileName();
            QFile::copy(srcTemp,destTemp);
        }else if(fileInfoList.at(i).isDir()){
            srcTemp=srcDir+"/"+fileInfoList.at(i).fileName();
            destTemp=destDir+"/"+fileInfoList.at(i).fileName();
            copyDir(srcTemp,destTemp);
        }
    }
}

QString MyTcpSocket::getName()
{
    QMutexLocker locker(&m_nameMutex);
    return m_name;
}

void MyTcpSocket::setName(const QString &newName)
{
    QMutexLocker locker(&m_nameMutex);
    m_name = newName;
}


//1.处理注册请求并返回响应PDU
void MyTcpSocket::registRequest(PDU* pdu){
    char caName[32]={'\0'};
    char caPwd[32]={'\0'};
    strncpy(caName,pdu->caData,32);
    strncpy(caPwd,pdu->caData+32,32);
    QString name=QString::fromUtf8(caName);
    QString pwd=QString::fromUtf8(caPwd);
    jointLog("处理用户["+name+"]注册请求：",0);
    emit registSignal(name,pwd,m_id);
}
void MyTcpSocket::handleRegistRequest(const QString &name,bool result,int tcpId){
    //校验id是否一致
    if(m_id!=tcpId){
        return;
    }
    PDU *resPdu=mkPDU(0);
    resPdu->uiMsgType=ENUM_MSG_TYPE_REGIST_RESPOND;         //注册回复
    if(result){
        QDir dir;
        if(dir.mkdir(QString("./%1").arg(name))){
            strcpy(resPdu->caData,REGIST_OK);
            jointLog("新用户注册成功，已创建新用户文件夹："+QString("./%1").arg(name),0);
        }else{
            strcpy(resPdu->caData,REGIST_FAILED);
            jointLog("用户注册成功，文件夹创建失败！",0);
        }
    }else{
        strcpy(resPdu->caData,REGIST_FAILED);
        jointLog("新用户注册失败！",0);
    }
    // 发送二进制数据包
    write((char*)resPdu,resPdu->uiPDULen);
    // 释放内存
    free(resPdu);
    resPdu=NULL;
}


//21.注销账号
void MyTcpSocket::logoffRequest(PDU *pdu)
{
    qDebug()<<"注销账号请求线程......："<<QThread::currentThread();
    char caName[32]={'\0'};
    strncpy(caName,pdu->caData,32);
    QString name=QString::fromUtf8(caName);
    jointLog("处理用户["+name+"]注销请求：",0);
    QString targetPath = QString("./%1").arg(name);
    QDir dir(targetPath);
    // 先检查目录是否存在
    if(!dir.exists()) {
        jointLog(targetPath+" 目录不存在",0);
    }else{
        if(dir.removeRecursively()) {
            jointLog("文件夹及内容删除成功：" + targetPath,0);
        }
    }
    emit logoffSignal(name,m_id);
}

void MyTcpSocket::handleLogoffRequest(const QString&name,bool result, int tcpId)
{
    //校验id是否一致
    if(m_id!=tcpId){
        return;
    }
    qDebug()<<"注销账号回复线程......："<<QThread::currentThread();
    PDU *resPdu=mkPDU(0);
    resPdu->uiMsgType=ENUM_MSG_TYPE_LOGOFF_RESPOND;         //注销回复
    if(result){
        strcpy(resPdu->caData,LOGOFF_OK);
        jointLog(QString("用户[%1]注销成功！").arg(name),0);
    }else{
        strcpy(resPdu->caData,LOGOFF_FAILED);
        jointLog(QString("用户[%1]注销失败！").arg(name),0);
    }
    // 发送二进制数据包
    write((char*)resPdu,resPdu->uiPDULen);
    // 释放内存
    free(resPdu);
    resPdu=NULL;
}

void MyTcpSocket::modifyInfoRequest(PDU *pdu)
{
    qDebug()<<"修改账号信息回复线程......："<<QThread::currentThread();
    jointLog("修改用户信息处理：");
    //从柔性数组中获取数据
    char* ptr = pdu->caMsg;
    int oldUsrNameLen = 0;
    memcpy(&oldUsrNameLen, ptr, sizeof(int));
    ptr += sizeof(int);
    QString oldUsrName = QString::fromUtf8(ptr, oldUsrNameLen);      //原文件路径
    ptr += oldUsrNameLen;

    int newUsrNameLen=0;
    memcpy(&newUsrNameLen,ptr,sizeof(int));
    ptr+=sizeof(int);
    QString newUsrName=QString::fromUtf8(ptr, newUsrNameLen);
    ptr+=newUsrNameLen;
    //读取文件名
    int newPwdLen=0;
    memcpy(&newPwdLen,ptr,sizeof(int));
    ptr+=sizeof(int);
    QString newPwd=QString::fromUtf8(ptr, newPwdLen);

    qDebug()<<"旧用户名--"<<oldUsrName<<",新用户名："<<newUsrName<<"，新密码："<<newPwd;

    QString oldPath = QString("./%1").arg(oldUsrName);
    QString newPath = QString("./%1").arg(newUsrName);
    QDir dir;
    // 先检查目录是否存在
    if(!dir.exists(oldPath)) {
        jointLog(oldPath+" 用户文件夹目录不存在",0);
    }else{
        if(dir.rename(oldPath,newPath)) {
            jointLog("文件夹名更新成功：" + newPath,0);
        }
    }
    emit modifyUsrInfoSignal(oldUsrName,newUsrName,newPwd,m_id);
}

void MyTcpSocket::handleModifyInfoRequest(const QString &name, bool result, int tcpId)
{
    //校验id是否一致
    if(m_id!=tcpId){
        return;
    }
    qDebug()<<"修改账号信息回复线程......："<<QThread::currentThread();
    PDU *resPdu=mkPDU(0);
    resPdu->uiMsgType=ENUM_MSG_TYPE_MODIFY_RESPOND;         //注销回复
    if(result){
        strcpy(resPdu->caData,MODIFYINFO_OK);
        jointLog(QString("用户[%1]更改信息成功！").arg(name),0);
    }else{
        strcpy(resPdu->caData,MODIFYINFO_FAILED);
        jointLog(QString("用户[%1]更改信息失败！").arg(name),0);
    }
    // 发送二进制数据包
    write((char*)resPdu,resPdu->uiPDULen);
    // 释放内存
    free(resPdu);
    resPdu=NULL;
}

//2.处理登录请求并返回响应PDU
void MyTcpSocket::loginRequest(PDU *pdu){
    char caName[32]={'\0'};
    char caPwd[32]={'\0'};
    strncpy(caName,pdu->caData,32);
    strncpy(caPwd,pdu->caData+32,32);
    QString name=QString::fromUtf8(caName);
    QString pwd=QString::fromUtf8(caPwd);
    jointLog("处理用户["+name+"]登录请求：",0);
    emit loginSignal(name,pwd,m_id);
}
void MyTcpSocket::handleLoginRequest(const QString&name,bool result,int tcpId){
    //校验id是否一致
    if(m_id!=tcpId){
        return;
    }
    PDU *resPdu=mkPDU(0);
    resPdu->uiMsgType=ENUM_MSG_TYPE_LOGIN_RESPOND;         //登录回复

    if(result){
        strcpy(resPdu->caData,LOGIN_OK);
        setName(name);
        jointLog(QString("用户[%1]登录成功！").arg(name),0);
        emit onlineSignalForward(name,tcpId);
    }else{
        strcpy(resPdu->caData,LOGIN_FAILED);
        jointLog(QString("用户[%1]登录失败！").arg(name),0);
    }

    // 发送二进制数据包
    write((char*)resPdu,resPdu->uiPDULen);
    // 释放内存
    free(resPdu);
    resPdu=NULL;
}

void MyTcpSocket::handleOnlineForwardFriendsRequest(const QStringList &usrList, int tcpId)
{
    //校验id是否一致
    if(m_id!=tcpId){
        return;
    }
    qDebug()<<"处理上线通知转发线程..."<<QThread::currentThread();
    for(int i=0;i<usrList.size();i++){
        PDU *pdu=mkPDU(0);
        pdu->uiMsgType=ENUM_MSG_TYPE_USR_ONLINE_NOTICE;         //登录回复
        strncpy(pdu->caData,getName().toStdString().c_str(), 32);
        emit forwardMsg(usrList.at(i),pdu);
    }
}

//3.查询所有在线用户并返回响应PDU
void MyTcpSocket::onlineUsersRequest(){
    jointLog("查询所有在线用户：");
    emit searchOnlineUsrsSignal(m_id);
}
void MyTcpSocket::handleOnlineUsersRequest(const QStringList &result,int tcpId){
    //校验id是否一致
    if(m_id!=tcpId){
        return;
    }
    //result.size() : 在线人数
    unsigned int uiMsgLen=result.size()*32;
    PDU *resPdu=mkPDU(uiMsgLen);
    resPdu->uiMsgType=ENUM_MSG_TYPE_ALL_ONLINE_USRS_RESPOND;
    for(int i=0;i<result.size();i++){
        strncpy((char*)resPdu->caMsg+i*32,
                result.at(i).toStdString().c_str(),
                32);
    }

    // 发送二进制数据包
    write((char*)resPdu,resPdu->uiPDULen);
    // 释放内存
    free(resPdu);
    resPdu=NULL;
}

//查询当前用户所有在线好友
void MyTcpSocket::getOnlineFriRequest(PDU *pdu)
{
    qDebug()<<"查询当前用户所有在线好友请求："<<QThread::currentThread();
    jointLog("查询当前用户所有在线好友请求：");
    char caUsrName[32] = {'\0'};
    strncpy(caUsrName, pdu -> caData, 32);
    QString usrName=QString::fromUtf8(caUsrName);
    emit searchOnlineFriendsSignal(usrName,m_id);
}
void MyTcpSocket::handleGetOnlineFriRequest(const QStringList& result, int tcpId)
{
    //校验id是否一致
    if(m_id!=tcpId){
        return;
    }
    //result.size() : 在线人数
    unsigned int uiMsgLen=result.size()*32;
    PDU *resPdu=mkPDU(uiMsgLen);
    resPdu -> uiMsgType = ENUM_MSG_TYPE_GET_ONLINE_FRIEND_RESPOND;
    for(int i=0;i<result.size();i++){
        strncpy((char*)resPdu->caMsg+i*32,
                result.at(i).toStdString().c_str(),
                32);
    }
    // 发送二进制数据包
    write((char*)resPdu,resPdu->uiPDULen);
    // 释放内存
    free(resPdu);
    resPdu=NULL;
}

//4.根据名称查找用户并返回响应PDU
void MyTcpSocket::searchUserRequest(PDU *pdu)
{
    char caSearchName[32]={'\0'};
    char caUsrName[32]={'\0'};
    strncpy(caSearchName,pdu->caData,32);
    strncpy(caUsrName,pdu->caData+32,32);
    QString searchName=QString::fromUtf8(caSearchName);
    QString usrName=QString::fromUtf8(caUsrName);
    emit searchUsrByNameSignal(searchName,usrName,m_id);
}

void MyTcpSocket::handleSearchResult(QList<UserInfo> resultList,int tcpId)
{
    //校验id是否一致
    if(m_id!=tcpId){
        return;
    }
    int totalSize=0;
    QList<QByteArray> nameBytesList;
    QList<int> nameLens;
    QList<int> onlines;
    QList<int> isFriends;
    for (const auto &info : resultList) {
        QByteArray nameBytes = info.name.toUtf8();
        int len = nameBytes.size();
        nameBytesList.append(nameBytes);
        nameLens.append(len);
        onlines.append(info.online);
        isFriends.append(info.isFriend);
        totalSize += sizeof(int) + sizeof(int) + sizeof(int) + len; // nameLen + online + isFriend + nameData
    }
    PDU *resPdu = mkPDU(totalSize);
    resPdu->uiMsgType=ENUM_MSG_TYPE_SEARCH_USR_RESPOND;
    char *p = resPdu->caMsg;
    for (int i = 0; i < resultList.size(); ++i) {
        int nameLen = nameLens[i];
        int online = onlines[i];
        int isFriend = isFriends[i];
        const QByteArray &nameData = nameBytesList[i];

        //name长度
        memcpy(p, &nameLen, sizeof(int));
        p += sizeof(int);
        //online
        memcpy(p, &online, sizeof(int));
        p += sizeof(int);
        //isFriend
        memcpy(p, &isFriend, sizeof(int));
        p += sizeof(int);
        //name
        memcpy(p, nameData.constData(), nameLen);
        p += nameLen;

        jointLog("Name: " + QString::fromUtf8(nameData)
                 + ", Online: " + QString::number(online)
                 + ", IsFriend: " + QString::number(isFriend));
    }

    // 发送二进制数据包
    write((char*)resPdu,resPdu->uiPDULen);
    // 释放内存
    free(resPdu);
    resPdu=NULL;
}



//5.处理添加好友请求并返回响应PDU
void MyTcpSocket::addFriendRequest(PDU *pdu)
{
    char caAddName[32]={'\0'};
    char caUsrName[32]={'\0'};
    strncpy(caAddName,pdu->caData,32);
    strncpy(caUsrName,pdu->caData+32,32);
    QString addName=QString::fromUtf8(caAddName);
    QString usrName=QString::fromUtf8(caUsrName);
    jointLog("用户"+usrName+"请求添加："+addName);
    emit addFriendSignal(addName,usrName,m_id,copyPDU(pdu));
}
void MyTcpSocket::handleAddFriendRequest(int ret,int tcpId,const QString&addName,PDU*pdu)
{
    //校验id是否一致
    if(m_id!=tcpId){
        return;
    }
    PDU*resPdu=mkPDU(0);
    resPdu->uiMsgType=ENUM_MSG_TYPE_ADD_FRIEND_RESPOND;         //添加好友回复

    if(ret==-1){                                    //系统出错
        strcpy(resPdu->caData,UNKNOW_ERROR);
    }else if(ret==0){                   //双方已经为好友
        strcpy(resPdu->caData, EXISTED_FRIEND);
    }else if(ret==1){                   //用户存在且在线
        jointLog("转发添加好友信息：");
        emit forwardMsg(addName,copyPDU(pdu));
        // 表示添加好友信息已发送到目标用户
        strcpy(resPdu -> caData, ADD_FRIEND_OK);
    }else if(ret==2){                   //用户存在且不在线
        strcpy(resPdu->caData, ADD_FRIEND_OFFLINE);
    }else if(ret==3){                   //用户不存在
        strcpy(resPdu->caData, ADD_FRIEND_NOEXIST);
    }

    // 发送二进制数据包
    write((char*)resPdu,resPdu->uiPDULen);
    // 释放内存
    free(resPdu);
    resPdu=NULL;

    if(pdu){
        free(pdu);
        pdu=NULL;
    }
}

//6.同意添加好友
void MyTcpSocket::handleAddFriendAgree(PDU *pdu)
{
    char caAddName[32] = {'\0'};
    char caUsrName[32] = {'\0'};
    // 拷贝读取的信息
    strncpy(caAddName, pdu -> caData, 32);
    strncpy(caUsrName, pdu -> caData + 32, 32);
    QString addName=QString::fromUtf8(caAddName);
    QString usrName=QString::fromUtf8(caUsrName);
    jointLog(addName+"同意添加好友！");

    // 将新的好友关系信息写入数据库
    emit agreeAddFriendSignal(addName, usrName);

    //转发消息
    emit forwardMsg(usrName, copyPDU(pdu));


    PDU *resPdu = mkPDU(0);
    resPdu -> uiMsgType =ENUM_MSG_TYPE_FLUSH_FRIEND_AND_TABLE_RESPOND;

    // 发送二进制数据包
    write((char*)resPdu,resPdu->uiPDULen);
    // 释放内存
    free(resPdu);
    resPdu=NULL;
}


//7.不同意添加好友
void MyTcpSocket::handleAddFriendDisagree(PDU *pdu)
{
    char caAddName[32] = {'\0'};
    char caUsrName[32] = {'\0'};
    strncpy(caAddName, pdu -> caData, 32);
    strncpy(caUsrName, pdu -> caData + 32, 32);
    QString addName=QString::fromUtf8(caAddName);
    QString usrName=QString::fromUtf8(caUsrName);
    jointLog(addName+"拒绝添加好友！");
    emit forwardMsg(usrName, copyPDU(pdu));
}

//8.刷新好友列表请求
void MyTcpSocket::flushFriendRequest(PDU *pdu)
{
    jointLog("刷新好友列表请求");
    char usrName[32] = {'\0'};
    strncpy(usrName, pdu -> caData, 32);
    QString name=QString::fromUtf8(usrName);

    emit flushFriendSignal(name,m_id);

}
void MyTcpSocket::handleFlushFriendRequest(const QStringList& strList,int tcpId)
{
    //校验id是否一致
    if(m_id!=tcpId){
        return;
    }
    unsigned int uiMsgLen = strList.size() / 2 * 36; // 36 char[32] 好友名字+ 4 int 在线状态
    PDU *resPdu = mkPDU(uiMsgLen);
    resPdu -> uiMsgType = ENUM_MSG_TYPE_FLUSH_FRIEND_RESPOND;
    for(int i = 0; i * 2 < strList.size(); i++)
    {
        strncpy((char*)(resPdu -> caMsg) + 36 * i, strList.at(i * 2).toStdString().c_str(), 32);
        strncpy((char*)(resPdu -> caMsg) + 36 * i + 32, strList.at(i * 2 + 1).toStdString().c_str(), 4);
    }
    // 发送二进制数据包
    write((char*)resPdu,resPdu->uiPDULen);
    // 释放内存
    free(resPdu);
    resPdu=NULL;
}

//9.删除好友请求
void MyTcpSocket::deleteFriendRequest(PDU *pdu)
{
    char caUsrName[32] = {'\0'};
    char caDelName[32] = {'\0'};
    // 拷贝读取的信息
    strncpy(caUsrName, pdu -> caData, 32);
    strncpy(caDelName, pdu -> caData + 32, 32);
    QString usrName=QString::fromUtf8(caUsrName);
    QString delName=QString::fromUtf8(caDelName);
    emit deleteFriendSignal(usrName,delName,m_id,copyPDU(pdu));
}

void MyTcpSocket::handleDeleteFriendRequest(bool result,int tcpId,const QString&delName,PDU*pdu)
{
    if(m_id!=tcpId){
        return;
    }
    PDU *resPdu = mkPDU(0);
    resPdu -> uiMsgType = ENUM_MSG_TYPE_DELETE_FRIEND_RESPOND;
    if(result){
        strcpy(resPdu -> caData, DEL_FRIEND_OK);
        jointLog("删除成功！");
    }else{
        strcpy(resPdu -> caData, DEL_FRIEND_FAILED);
        jointLog("删除失败！");
    }

    // 发送二进制数据包
    write((char*)resPdu,resPdu->uiPDULen);
    // 释放内存
    free(resPdu);
    resPdu=NULL;

    emit forwardMsg(delName, copyPDU(pdu));

    if(pdu){
        free(pdu);
        pdu=NULL;
    }
}

//10.群聊请求
void MyTcpSocket::groupChatRequest(PDU *pdu)
{
    char caUsrName[32] = {'\0'};
    strncpy(caUsrName, pdu -> caData, 32);
    QString usrName=QString::fromUtf8(caUsrName);
    emit groupChatSignal(usrName,m_id,copyPDU(pdu));
}
void MyTcpSocket::handleGroupChatRequest(const QStringList& usrList,int tcpId,PDU*pdu)
{
    if(m_id!=tcpId){
        return;
    }
    QString msg = QString::fromUtf8(pdu->caMsg, pdu->uiMsgLen);
    for(int i=0;i<usrList.size();i+=2){
        jointLog("转发给："+usrList.at(i)+",消息内容："+msg);
        emit forwardMsg(usrList.at(i), copyPDU(pdu));
    }

    if(pdu){
        free(pdu);
        pdu=NULL;
    }
}


//11.私聊请求
void MyTcpSocket::handlePrivateChatRequest(PDU *pdu)
{
    char caUsrName[32]={'\0'};
    char caChatName[32] = {'\0'};
    strncpy(caUsrName, pdu -> caData, 32);
    strncpy(caChatName, pdu -> caData+32, 32);
    QString usrName=QString::fromUtf8(caUsrName);
    QString chatName=QString::fromUtf8(caChatName);
    QString msg = QString::fromUtf8(pdu->caMsg, pdu->uiMsgLen);
    jointLog(QString(usrName)+" 发送给 "+QString(chatName)+" 消息内容："+msg);

    emit forwardMsg(chatName, copyPDU(pdu));
}

//12.用户下线
void MyTcpSocket::usrOfflineRequest(PDU*pdu){
    char usrName[32]={'\0'};
    strncpy(usrName,pdu->caData,32);
    QString name=QString::fromUtf8(usrName);
    emit usrOfflineSignal(name,m_id);
}
void MyTcpSocket::handleUsrOfflineRequest(const QString &name,bool result,int tcpId)
{
    //校验id是否一致
    if(m_id!=tcpId){
        return;
    }
    if(result){
        jointLog("用户"+QString(name)+"已下线！");
        emit offlineSignalForward(name,tcpId);
        setName("");
    }else{
        jointLog("用户"+QString(name)+"未成功下线！");
    }
}

void MyTcpSocket::handleOfflineForwardFriendsRequest(const QString&usrName,const QStringList &usrList, int tcpId)
{
    //校验id是否一致
    if(m_id!=tcpId){
        return;
    }
    qDebug()<<"处理下线通知转发线程..."<<QThread::currentThread();
    for(int i=0;i<usrList.size();i++){
        PDU *pdu=mkPDU(0);
        pdu->uiMsgType=ENUM_MSG_TYPE_USR_OFFLINE_NOTICE;         //登录回复
        strncpy(pdu->caData,usrName.toStdString().c_str(), 32);
        emit forwardMsg(usrList.at(i),pdu);
    }
}

//13.创建文件夹请求处理  +
PDU *MyTcpSocket::handleCreateDirRequest(PDU *pdu)
{
    QDir dir;
    // 从柔性数组中获取数据
    char* ptr = pdu->caMsg;
    // 读取第一个字符串
    int pathLen = 0;
    memcpy(&pathLen, ptr, sizeof(int));
    ptr += sizeof(int);
    QString curPath = QString::fromUtf8(ptr, pathLen);
    ptr += pathLen;
    // 读取第二个字符串
    int nameLen = 0;
    memcpy(&nameLen, ptr, sizeof(int));
    ptr += sizeof(int);
    QString newDir = QString::fromUtf8(ptr, nameLen);
    PDU*resPdu = mkPDU(0);
    resPdu -> uiMsgType = ENUM_MSG_TYPE_CREATE_DIR_RESPOND;
    jointLog("创建文件夹请求：在 "+curPath+" 目录下创建文件夹："+newDir);
    bool ret=dir.exists(curPath);
    if(ret){                    //当前目录存在
        jointLog("当前目录："+curPath+" 存在");
        QString newPath=curPath+"/"+newDir;
        ret=dir.exists(newPath);
        if(ret){        //文件夹已存在
            strcpy(resPdu -> caData, DIR_NAME_EXIST);
            jointLog("文件夹："+newPath+" 已存在！");
        }else{
            dir.mkdir(newPath); // 创建文件夹
            strcpy(resPdu -> caData, CREATE_DIR_OK);
            jointLog("创建文件夹："+newPath+" 成功！");
        }
    }else{             //当前目录不存在
        strcpy(resPdu -> caData, DIR_NO_EXIST);
        jointLog("当前目录："+curPath+" 不存在！");
    }

    return resPdu;
}


//14.刷新文件夹请求处理 +
PDU *MyTcpSocket::handleFlushDirRequest(PDU *pdu)
{
    QString curPath = QString::fromUtf8(pdu->caMsg, pdu->uiMsgLen);
    jointLog("在当前路径 "+curPath+" 下刷新文件夹:");
    QDir dir(curPath);
    QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
    int fileCount=fileInfoList.size();
    QList<QByteArray> fileNames;
    QList<int> nameLens;
    QList<int> fileTypes;
    int totalFileInfoSize = 0;
    for (const QFileInfo& fi : fileInfoList) {
        QByteArray name = fi.fileName().toUtf8();
        int len = name.size();
        int type = fi.isDir() ? 0 : 1;
        fileNames.append(name);
        nameLens.append(len);
        fileTypes.append(type);
        totalFileInfoSize += sizeof(int) + sizeof(int) + len;  // nameLen + fileType + name data
    }
    PDU *resPdu=mkPDU(totalFileInfoSize);
    resPdu -> uiMsgType = ENUM_MSG_TYPE_FLUSH_DIR_RESPOND;
    char* p = resPdu->caMsg;
    for(int i=0;i<fileCount;i++){
        int nameLen=nameLens[i];
        int fileType = fileTypes[i];
        const QByteArray& nameBytes = fileNames[i];
        // 写入 nameLen
        memcpy(p, &nameLen, sizeof(int));
        p += sizeof(int);
        // 写入 fileType
        memcpy(p, &fileType, sizeof(int));
        p += sizeof(int);
        // 写入 UTF-8 编码的文件名
        memcpy(p, nameBytes.constData(), nameLen);
        p += nameLen;

        jointLog("是否为文件："+QString::number(fileType)+
                                              " ,文件/文件夹名："+QString::fromUtf8(nameBytes, nameLen));
    }
    jointLog("总写入caMsg字节数："+QString::number(totalFileInfoSize));
    return resPdu;
}

//15.处理删除文件/文件夹请求   +
PDU *MyTcpSocket::handleDelFileOrDirRequest(PDU *pdu)
{
    QDir dir;
    //从柔性数组中获取数据
    char* ptr = pdu->caMsg;
    // 读取第一个字符串
    int pathLen = 0;
    memcpy(&pathLen, ptr, sizeof(int));
    ptr += sizeof(int);
    QString curPath = QString::fromUtf8(ptr, pathLen);
    ptr += pathLen;
    // 读取第二个字符串
    int nameLen = 0;
    memcpy(&nameLen, ptr, sizeof(int));
    ptr += sizeof(int);
    QString newDir = QString::fromUtf8(ptr, nameLen);
    QString newPath=curPath+"/"+newDir;
    PDU*resPdu = mkPDU(0);
    resPdu -> uiMsgType = ENUM_MSG_TYPE_DELETE_DIR_FILE_RESPOND;
    jointLog("当前路径："+newPath);
    if(!dir.exists(newPath)) {
        jointLog("当前文件路径不存在！");
        strcpy(resPdu -> caData, PATH_NOT_EXIST);
    }else{
        QFileInfo fileInfo(newPath);
        if(fileInfo.isDir()){           //删除文件夹
            dir.setPath(newPath);
            if(dir.removeRecursively()){
                jointLog("文件夹删除成功！");
                strcpy(resPdu -> caData, DELETE_DIR_OK);
            }else{
                jointLog("文件夹删除失败！");
                strcpy(resPdu -> caData, DELETE_DIR_FAILED);
            }
        }else if(fileInfo.isFile()){        //删除文件
            if(dir.remove(newPath)){
                jointLog("文件删除成功！");
                strcpy(resPdu -> caData, DELETE_FILE_OK);
            }else{
                jointLog("文件删除失败！");
                strcpy(resPdu -> caData, DELETE_FILE_FAILED);
            }
        }
    }

    return resPdu;
}

//16.重命名文件和文件夹请求    +
PDU *MyTcpSocket::handleRenameFileRequest(PDU *pdu)
{
    QDir dir;
    PDU*resPdu = mkPDU(0);
    resPdu -> uiMsgType = ENUM_MSG_TYPE_RENAME_DIR_FILE_RESPOND;

    //从柔性数组中获取数据
    char* ptr = pdu->caMsg;
    // 读取第一个字符串
    int pathLen = 0;
    memcpy(&pathLen, ptr, sizeof(int));
    ptr += sizeof(int);
    QString curPath = QString::fromUtf8(ptr, pathLen);      //当前路径
    ptr += pathLen;

    // 读取第二个字符串
    int oldNameLen = 0;
    memcpy(&oldNameLen, ptr, sizeof(int));
    ptr += sizeof(int);

    QString oldName = QString::fromUtf8(ptr, oldNameLen);      //旧name
    ptr += oldNameLen;

    //读取第三个字符串
    int newNameLen = 0;
    memcpy(&newNameLen, ptr, sizeof(int));
    ptr += sizeof(int);

    QString newName = QString::fromUtf8(ptr, newNameLen);      //新name
    jointLog("更改文件名称：");
    dir.setPath(curPath);
    if(dir.rename(oldName,newName)){
        jointLog("当前路径："+curPath+",旧文件名："+oldName+",新文件名："+newName);
        strcpy(resPdu -> caData, RENAME_OK);
    }else{
        jointLog("改名失败！");
        strcpy(resPdu -> caData, RENAME_FAILED);
    }

    return resPdu;
}

//17.进入文件夹请求处理 +
PDU *MyTcpSocket::handleEntryDirRequest(PDU *pdu)
{
    //从柔性数组中获取数据
    char* ptr = pdu->caMsg;
    // 读取第一个字符串
    int pathLen = 0;
    memcpy(&pathLen, ptr, sizeof(int));
    ptr += sizeof(int);
    QString curPath = QString::fromUtf8(ptr, pathLen);      //当前路径
    ptr += pathLen;

    // 读取第二个字符串
    int entryNameLen = 0;
    memcpy(&entryNameLen, ptr, sizeof(int));
    ptr += sizeof(int);
    QString entryName = QString::fromUtf8(ptr, entryNameLen);      //文件夹名

    QString entryPath=QString("%1/%2").arg(curPath).arg(entryName);
    QFileInfo fileInfo(entryPath);

    PDU*resPdu=NULL;

    if(!fileInfo.isDir()) {
        resPdu = mkPDU(0);
        resPdu -> uiMsgType = ENUM_MSG_TYPE_ENTER_DIR_RESPOND;
        //打开该文件
        jointLog(entryPath+"：非文件夹，无法进入！");
        strcpy(resPdu -> caData, ENTER_DIR_FAILED);
    }
    else{
        jointLog("进入文件夹："+entryPath);
        QDir dir(entryPath);
        QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
        int fileCount=fileInfoList.size();
        QList<QByteArray> fileNames;
        QList<int> nameLens;
        QList<int> fileTypes;
        int totalFileInfoSize = 0;
        for (const QFileInfo& fi : fileInfoList) {
            QByteArray name = fi.fileName().toUtf8();
            int len = name.size();
            int type = fi.isDir() ? 0 : 1;
            fileNames.append(name);
            nameLens.append(len);
            fileTypes.append(type);
            totalFileInfoSize += sizeof(int) + sizeof(int) + len;  // nameLen + fileType + name data
        }

        resPdu=mkPDU(totalFileInfoSize);
        resPdu -> uiMsgType = ENUM_MSG_TYPE_ENTER_DIR_RESPOND;
        char* p = resPdu->caMsg;
        strcpy(resPdu->caData, ENTER_DIR_OK);

        for(int i=0;i<fileCount;i++){
            int nameLen=nameLens[i];
            int fileType = fileTypes[i];
            const QByteArray& nameBytes = fileNames[i];
            // 写入 nameLen
            memcpy(p, &nameLen, sizeof(int));
            p += sizeof(int);
            // 写入 fileType
            memcpy(p, &fileType, sizeof(int));
            p += sizeof(int);
            // 写入 UTF-8 编码的文件名
            memcpy(p, nameBytes.constData(), nameLen);
            p += nameLen;

            jointLog("是否为文件："+QString::number(fileType)+
                                                  " ,文件/文件夹名："+QString::fromUtf8(nameBytes, nameLen));
        }
        jointLog("总写入caMsg字节数："+QString::number(totalFileInfoSize));
    }

    return resPdu;
}

//18.上传文件请求处理   +
PDU *MyTcpSocket::handleUploadFileRequest(PDU *pdu)
{
    jointLog("上传文件请求：");
    //从柔性数组中获取数据
    char* ptr = pdu->caMsg;
    // 读取当前路径
    int pathLen = 0;
    memcpy(&pathLen, ptr, sizeof(int));
    ptr += sizeof(int);
    //当前路径
    QString curPath = QString::fromUtf8(ptr, pathLen);
    ptr += pathLen;

    // 读取文件名
    int nameLen = 0;
    memcpy(&nameLen, ptr, sizeof(int));
    ptr += sizeof(int);
    QString fileName = QString::fromUtf8(ptr, nameLen);
    ptr += nameLen;

    //读取文件大小
    qint64 fileSize=0;
    memcpy(&fileSize, ptr, sizeof(qint64));

    jointLog("当前路径："+curPath+",文件名："+fileName+",文件大小："+QString::number(fileSize)+"字节");
    QString jointPath=QString("%1/%2").arg(curPath).arg(fileName);

    PDU*resPdu = mkPDU(0);
    resPdu -> uiMsgType = ENUM_MSG_TYPE_UPLOAD_FILE_RESPOND;

    m_file.setFileName(jointPath);
    // 以只写的方式打开文件，文件如果不存在会自动创建
    if(m_file.open(QIODevice::WriteOnly)){
        m_upLoad=true;              //准备接收文件数据
        m_total=fileSize;           //文件总大小，字节为单位
        m_recved=0;                 //已接收大小
        //开始上传文件
        strcpy(resPdu -> caData, UPLOAD_FILE_START);
    }else{
        //打开文件失败
        strcpy(resPdu -> caData, OPEN_FILE_FAILED);
    }
    return resPdu;
}

//19.下载文件请求处理   +
PDU *MyTcpSocket::handleDownloadFileRequest(PDU *pdu)
{
    jointLog("下载文件请求：");
    //从柔性数组中获取数据
    char* ptr = pdu->caMsg;
    // 读取第一个字符串
    int pathLen = 0;
    memcpy(&pathLen, ptr, sizeof(int));
    ptr += sizeof(int);
    QString curPath = QString::fromUtf8(ptr, pathLen);      //当前路径
    ptr += pathLen;

    // 读取第二个字符串
    int nameLen = 0;
    memcpy(&nameLen, ptr, sizeof(int));
    ptr += sizeof(int);
    QString fileName = QString::fromUtf8(ptr, nameLen);      //文件名
    QString jointPath=QString("%1/%2").arg(curPath).arg(fileName);
    QFileInfo fileInfo(jointPath);
    m_file.setFileName(jointPath);
    PDU*resPdu=NULL;
    if(fileInfo.isDir()){       //文件夹
        jointLog("当前选中单元为文件夹，无法下载！");
        resPdu = mkPDU(0);
        resPdu -> uiMsgType = ENUM_MSG_TYPE_DOWNLOAD_FILE_RESPOND;
        strcpy(resPdu -> caData, NON_FILE);
    }else{
        if(m_file.open(QIODevice::ReadOnly)){
            qint64 fileSize=fileInfo.size();
            m_total=fileSize;
            jointLog("当前路径："+curPath+",文件名："+fileName+",文件大小："+QString::number(fileSize)+"字节");
            QByteArray nameData =fileName.toUtf8();           // 文件名
            unsigned int totalMsgLen=4+nameData.size()+sizeof(qint64);
            resPdu=mkPDU(totalMsgLen);
            // 写入数据到柔性数组
            char* P = resPdu->caMsg;
            //写入文件名长度
            int nameLen=nameData.size();
            memcpy(P,&nameLen,sizeof(int));
            P+=sizeof(int);
            //写入文件名数据
            memcpy(P,nameData.constData(),nameLen);
            P+=nameLen;
            //写入文件大小
            memcpy(P,&fileSize,sizeof(qint64));
            resPdu -> uiMsgType = ENUM_MSG_TYPE_DOWNLOAD_FILE_RESPOND;
            strcpy(resPdu -> caData, DOWNLOAD_FILE_START);
            m_timer -> start(1000);             // 开始计时器1000ms
        }else{
            jointLog("文件打开失败！");
            resPdu = mkPDU(0);
            resPdu -> uiMsgType = ENUM_MSG_TYPE_DOWNLOAD_FILE_RESPOND;
            strcpy(resPdu -> caData, OPEN_FILE_FAILED);
        }
    }

    return resPdu;
}

//20.移动文件请求处理
PDU *MyTcpSocket::handleMoveFileRequest(PDU *pdu)
{
    jointLog("移动文件处理：");
    //从柔性数组中获取数据
    char* ptr = pdu->caMsg;
    // 读取原文件路径
    int sourcePathLen = 0;
    memcpy(&sourcePathLen, ptr, sizeof(int));
    ptr += sizeof(int);
    QString sourcePath = QString::fromUtf8(ptr, sourcePathLen);      //原文件路径
    ptr += sourcePathLen;
    //读取目标路径
    int targetPathLen=0;
    memcpy(&targetPathLen,ptr,sizeof(int));
    ptr+=sizeof(int);
    QString targetPath=QString::fromUtf8(ptr, targetPathLen);
    ptr+=targetPathLen;
    //读取文件名
    int fileNameLen=0;
    memcpy(&fileNameLen,ptr,sizeof(int));
    ptr+=sizeof(int);
    QString fileName=QString::fromUtf8(ptr, fileNameLen);

    jointLog("原文件路径："+sourcePath+",文件名："+fileName
                                          +",目标路径："+targetPath);
    QString sourceFile=QString("%1/%2").arg(sourcePath).arg(fileName);
    QString targetFile=QString("%1/%2").arg(targetPath).arg(fileName);

    QFileInfo fileInfo(sourceFile);

    PDU*resPdu = mkPDU(0);
    resPdu -> uiMsgType = ENUM_MSG_TYPE_MOVE_FILE_RESPOND;

    if(fileInfo.isFile())       //如果是文件
    {
        if (QFile::rename(sourceFile, targetFile)) // 移动文件
        {
            jointLog("移动文件成功！");
            strcpy(resPdu -> caData, MOVE_FILE_OK);
        }
        else
        {
            jointLog("移动文件失败！");
            strcpy(resPdu -> caData, MOVE_FILE_FAILED);
        }
    }else{                     //如果是文件夹
        QDir dir;
        if (dir.rename(sourceFile, targetFile)) // 移动文件夹
        {
            jointLog("移动文件夹成功！");
            strcpy(resPdu -> caData, MOVE_DIR_OK);
        }
        else
        {
            jointLog("移动文件夹失败！");
            strcpy(resPdu -> caData, MOVE_DIR_FAILED);
        }
    }
    return resPdu;
}

//22.分享文件请求处理
void MyTcpSocket::handleShareFileRequest(PDU *pdu)
{
    jointLog("分享文件请求处理：");
    QList<QString> friendList;
    PDU*resPdu=mkPDU(0);
    resPdu->uiMsgType=ENUM_MSG_TYPE_SHARE_FILE_RESPOND;         //分享文件回复
    char caUsrName[32] = {'\0'};
    char friendSize[32]={'\0'};
    char friendTemp[32]={'\0'};
    strncpy(caUsrName, pdu -> caData, 32);
    strncpy(friendSize, pdu -> caData+32, 32);
    QString usrName=QString::fromUtf8(caUsrName);
    QString sizeStr=QString::fromUtf8(friendSize);
    int size=sizeStr.toInt();
    // 从柔性数组中获取数据
    char* ptr = pdu->caMsg;
    for(int i=0;i<size;i++){
        strncpy(friendTemp,(char*)pdu->caMsg+i*32,32);
        QString friendName=QString::fromUtf8(friendTemp);
        friendList.append(friendName);
        //转发分享文件消息
        ptr+=32;
    }
    // 读取第一个字符串
    int pathDataLen = 0;
    memcpy(&pathDataLen, ptr, sizeof(int));
    ptr += sizeof(int);
    QString curPath = QString::fromUtf8(ptr, pathDataLen);
    ptr += pathDataLen;
    // 读取第二个字符串
    int nameLen = 0;
    memcpy(&nameLen, ptr, sizeof(int));
    ptr += sizeof(int);
    QString fileName = QString::fromUtf8(ptr, nameLen);
    QString jointPath=QString("%1/%2").arg(curPath).arg(fileName);

    QFileInfo fileInfo(jointPath);
    if(fileInfo.isFile())       //如果是文件
    {
        jointLog("待分享文件路径："+jointPath);
        strcpy(resPdu -> caData, SHARE_FILE_OK);
    }else{
        jointLog("待分享文件夹路径："+jointPath);
        strcpy(resPdu -> caData, SHARE_DIR_OK);
    }

    // 发送二进制数据包
    write((char*)resPdu,resPdu->uiPDULen);
    // 释放内存
    free(resPdu);
    resPdu=NULL;

    for(QString str:friendList){
        QByteArray jointPathData = jointPath.toUtf8();
        int jointPathDataLen=jointPathData.size();
        PDU*pdu=mkPDU(4+jointPathDataLen);
        pdu->uiMsgType=ENUM_MSG_TYPE_SHARE_FILE_REQUEST;
        strncpy(pdu->caData, caUsrName, 32);
        char *ptr=pdu->caMsg;
        memcpy(ptr,&jointPathDataLen,sizeof(int));
        ptr+=sizeof(int);
        memcpy(ptr,jointPathData.constData(),jointPathDataLen);
        emit forwardMsg(str,pdu);
    }
}

//接收文件
PDU *MyTcpSocket::handleRecvFileRequest(PDU *pdu)
{
    jointLog("同意接收分享文件！");
    // 从柔性数组中获取数据
    char* ptr = pdu->caMsg;
    // 读取第一个字符串
    int pathDataLen = 0;
    memcpy(&pathDataLen, ptr, sizeof(int));
    ptr += sizeof(int);
    QString pathData = QString::fromUtf8(ptr, pathDataLen);

    QFileInfo fileInfo(pathData);
    PDU*resPdu=mkPDU(0);
    resPdu->uiMsgType=ENUM_MSG_TYPE_SHARE_FILE_SUCCESS;
    if(fileInfo.isFile()){
        QString newPath=QString("./%1/%2").arg(getName()).arg(fileInfo.fileName());
        jointLog("文件接收新路径："+newPath);
        if(QFile::copy(pathData,newPath)){
            jointLog("文件接收成功！");
            strcpy(resPdu -> caData, RECV_FILE_OK);
        }else{
            jointLog("文件接收失败！");
            strcpy(resPdu -> caData, RECV_FILE_FAILED);
        }
    }else if(fileInfo.isDir()){
        QString newPath=QString("./%1/%2").arg(getName()).arg(fileInfo.fileName());
        jointLog("文件夹接收新路径："+newPath);
        copyDir(pathData,newPath);
        strcpy(resPdu -> caData, RECV_DIR_OK);
    }
    return resPdu;
}



//接收客户端发送数据
void MyTcpSocket::recvMsg()
{
    if(!m_upLoad){
        //非上传文件状态
        unsigned int uiPDULen=0;
        // 总数据大小
        read((char*)&uiPDULen,sizeof(unsigned int));
        // 实际消息大小，sizeof(PDU)只会计算结构体大小，而不是分配的大小
        unsigned int uiMsgLen=uiPDULen-sizeof(PDU);
        PDU*pdu=mkPDU(uiMsgLen);
        read((char *)pdu+sizeof(unsigned int),uiPDULen-sizeof(unsigned int));

        // 根据不同消息类型，执行不同操作
        PDU *resPdu=NULL;
        qDebug()<<"当前用户："<<getName()<<",当前消息类型哈哈哈哈哈："<<pdu->uiMsgType;
        switch(pdu->uiMsgType)
        {
        case ENUM_MSG_TYPE_THREAD_TARGET:      //线程标识
        {
            break;
        }
        case ENUM_MSG_TYPE_REGIST_REQUEST:          //注册请求
        {
            registRequest(pdu);
            break;
        }
        case ENUM_MSG_TYPE_LOGIN_REQUEST:          //登录请求
        {
            loginRequest(pdu);
            break;
        }
        case ENUM_MSG_TYPE_LOGOFF_REQUEST:{         //注销账号请求
            logoffRequest(pdu);
            break;
        }
        case ENUM_MSG_TYPE_ALL_ONLINE_USRS_REQUEST:          //所有在线用户请求
        {
            onlineUsersRequest();
            break;
        }

        case ENUM_MSG_TYPE_SEARCH_USR_REQUEST:          //根据用户名称查找请求
        {
            searchUserRequest(pdu);
            break;
        }
        case ENUM_MSG_TYPE_ADD_FRIEND_REQUEST:  //添加好友请求
        {
            addFriendRequest(pdu);
            break;
        }
        case ENUM_MSG_TYPE_ADD_FRIEND_AGREE:{           //同意添加好友
            handleAddFriendAgree(pdu);
            break;
        }
        case ENUM_MSG_TYPE_ADD_FRIEND_DISAGREE:{           //不同意添加好友
            handleAddFriendDisagree(pdu);
            break;
        }

        case ENUM_MSG_TYPE_FLUSH_FRIEND_REQUEST:{           //刷新好友请求
            flushFriendRequest(pdu);
            break;
        }

        case ENUM_MSG_TYPE_DELETE_FRIEND_REQUEST:{              //删除好友请求
            deleteFriendRequest(pdu);
            break;
        }

        case ENUM_MSG_TYPE_PRIVATE_CHAT_REQUEST:{               //私聊请求
            handlePrivateChatRequest(pdu);
            break;
        }

        case ENUM_MSG_TYPE_GROUP_CHAT_REQUEST:{                 //群聊请求
            groupChatRequest(pdu);
            break;
        }

        case ENUM_MSG_TYPE_USR_OFFLINE_REQUEST:{                //用户下线请求
            usrOfflineRequest(pdu);
            break;
        }
        case ENUM_MSG_TYPE_CREATE_DIR_REQUEST:{             //创建文件夹请求
            resPdu=handleCreateDirRequest(pdu);
            break;
        }
        case ENUM_MSG_TYPE_FLUSH_DIR_REQUEST:{          //刷新文件夹请求
            resPdu=handleFlushDirRequest(pdu);
            break;
        }
        case ENUM_MSG_TYPE_DELETE_DIR_FILE_REQUEST:{   //删除文件/文件夹请求
            resPdu=handleDelFileOrDirRequest(pdu);
            break;
        }

        case ENUM_MSG_TYPE_RENAME_DIR_FILE_REQUEST:{         //重命名文件/文件夹请求
            resPdu=handleRenameFileRequest(pdu);
            break;
        }
        case ENUM_MSG_TYPE_ENTER_DIR_REQUEST:{          //进入文件夹
            resPdu=handleEntryDirRequest(pdu);
            break;
        }
        case ENUM_MSG_TYPE_UPLOAD_FILE_REQUEST:{            //上传文件请求
            resPdu=handleUploadFileRequest(pdu);
            break;
        }

        case ENUM_MSG_TYPE_DOWNLOAD_FILE_REQUEST:{          //下载文件请求
            resPdu=handleDownloadFileRequest(pdu);
            break;
        }

        case ENUM_MSG_TYPE_MOVE_FILE_REQUEST:   //移动文件请求
        {
            resPdu=handleMoveFileRequest(pdu);
            break;
        }

        case ENUM_MSG_TYPE_GET_ONLINE_FRIEND_REQUEST://获取在线好友列表
        {
            getOnlineFriRequest(pdu);
            break;
        }

        case ENUM_MSG_TYPE_SHARE_FILE_REQUEST:          //分享文件请求
        {
            handleShareFileRequest(pdu);
            break;
        }

        case ENUM_MSG_TYPE_RECV_SHARE_FILE_AGREE:         //同意接收分享文件
        {
            resPdu=handleRecvFileRequest(pdu);
            break;
        }

        case ENUM_MSG_TYPE_RECV_SHARE_FILE_DISAGREE:        //不同意接收分享文件
        {
            //
            jointLog("不同意接收分享文件！");
            break;
        }
        case ENUM_MSG_TYPE_MODIFY_REQUEST:
        {
            modifyInfoRequest(pdu);
            break;
        }

        default:
            break;
        }

        if(resPdu!=NULL){
            // 发送二进制数据包
            write((char*)resPdu,resPdu->uiPDULen);
            // 释放内存
            free(resPdu);
            resPdu=NULL;
        }
        free(pdu);
        pdu=NULL;
    }else{
        // 接收文件数据
        QByteArray buffer = readAll();
        m_file.write(buffer);       //文件之前被打开过，向文件中写入数据
        m_recved+=buffer.size();
        int percent = (m_recved * 100) / m_total;
        if (percent != m_lastPercent) {
            m_lastPercent = percent;
            jointLog(QString("文件上传进度：%1%").arg(percent)+" ,当前已接收数据总量："+QString::number(m_recved));
        }
        PDU* resPdu = NULL;
        if(m_total==m_recved){          //传送完成
            m_file.close();
            m_upLoad=false;
            m_lastPercent=0;
            resPdu = mkPDU(0);
            resPdu -> uiMsgType = ENUM_MSG_TYPE_UPLOAD_FILE_RESPOND;
            jointLog("上传文件成功！");
            strcpy(resPdu -> caData, UPLOAD_FILE_OK);
        }else if(m_total<m_recved){     //传送失败
            m_file.close();
            m_upLoad=false;
            m_lastPercent=0;
            resPdu = mkPDU(0);
            resPdu -> uiMsgType = ENUM_MSG_TYPE_UPLOAD_FILE_RESPOND;
            jointLog("上传文件失败！");
            strcpy(resPdu -> caData, UPLOAD_FILE_FAILED);
        }
        // 响应客户端
        if(resPdu!=NULL)
        {
            jointLog("接收数据结束，向客户端返回结果...");
            write((char*)resPdu, resPdu -> uiPDULen);
            // 释放空间
            free(resPdu);
            resPdu = NULL;
        }
    }
}

//下载文件数据（服务器-->本机）
void MyTcpSocket::downLoadFileData()
{
    m_timer->stop();
    // 二进制形式传输文件
    char *pBuffer = new char[4096]; // 4096个字节读写效率更高
    qint64 iActualSize = 0;         // 实际读取文件内容大小
    qint64 totalSize=0;
    m_lastPercent=0;
    while(true){
        iActualSize=m_file.read(pBuffer,4096);
        if (iActualSize > 0 && iActualSize <= 4096)
        {
            totalSize+=iActualSize;
            int percent = (totalSize * 100) / m_total;
            if (percent != m_lastPercent) {
                m_lastPercent = percent;
                jointLog(QString("文件下载进度：%1%").arg(percent)+" ,当前已发送数据总量："+QString::number(totalSize));
            }
            write(pBuffer, iActualSize);
        }
        else if (iActualSize == 0)
        {
            jointLog("发送文件数据完成！");
            break;
        }else{
            jointLog("发送文件数据给客户端出错！");
            break;
        }
    }
    m_total=0;
    m_lastPercent = 0;
    m_file.close();
    delete []pBuffer;
    pBuffer=NULL;
    m_file.setFileName("");
}

//转发数据
void MyTcpSocket::sendData(MyTcpSocket *tcpSocket, PDU *pdu)
{
    if(this==tcpSocket){
        qDebug()<<"转发数据线程......："<<QThread::currentThread();
        write((char*)pdu,pdu->uiPDULen);
        if(pdu){
            qDebug()<<"哈哈哈~~~";
            free(pdu);
            pdu=NULL;
        }
    }
}

//设置当前用户id
void MyTcpSocket::setTcpId(int newTcpId)
{
    QMutexLocker locker(&m_idMutex);
    m_id = newTcpId;
}
//拼接一行日志
void MyTcpSocket::jointLog(const QString &txt,int flag)
{
    QString jointMsg;
    if(flag==0){
        jointMsg = "@@系统@@ :"+txt;
    }else{
        jointMsg = "$$用户"+getName()+"$$ :"+txt;
    }
    emit logSignal(jointMsg);
}

